﻿using GameDataTempshitEditor.Widgets;
using Red.GameData;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GameDataTempshitEditor.DataEditors
{
    /// <summary>
    /// Property item representing array in the source data
    /// </summary>
    public class GameData_PropertyArray : Widgets.PropertyItemBase
    {
        public GameData_PropertyArray(PropertyItemBase parent, EditorContext context, EditorPropertyView propInfo, bool canEdit)
            : base(parent, propInfo.Name + "[]")
        {
            _Context = context;
            _PropInfo = propInfo;
            _CanEdit = canEdit;

            // expand flag
            _CanExpand = (_PropInfo.CachedNumArrayElements != 0);
            _LocalCachedCompoundGenerationId = _PropInfo.CachedCompoundGenerationId;
        }

        public override bool IsOverriden()
        {
            return _PropInfo.CachedIsOverriden;
        }

        public override bool IsReadOnly()
        {
            return _PropInfo.IsReadOnly || !_CanEdit || !_PropInfo.CachedIsWritable;
        }

        public override void CreateElementActions(ref List<PropertyItemAction> actions)
        {
            if (IsReadOnly())
                return;

            // add new element to array
            if (_PropInfo.IsInlined)
                actions.Add(new PropertyItemAction_Button(this, "New", Action_AddElement));
            else
                actions.Add(new PropertyItemAction_Button(this, "Add", Action_AddElement));

            // non-key overridden values can be reset
            if (_PropInfo.CachedIsOverriden)
            {
                actions.Add(new PropertyItemAction_Button(this, "Reset", Action_ResetPropertyOverride));
            }
        }

        bool Action_ResetPropertyOverride(PropertyItemBase item, ref string errorString)
        {
            // create and dispatch action
            var action = Red.GameData.Actions.RemoveOverride.Create(_Context, _PropInfo.Object.RawData, _PropInfo.Name, Guid.Empty);
            return _Context.ActionHistory.Execute(action, ref errorString);
        }

        bool Action_AddElement(PropertyItemBase item, ref string errorString)
        {
            // create and dispatch action
            var action = Red.GameData.Actions.AddArrayElement.Create(_Context, _PropInfo.Object.RawData, _PropInfo.Name);
            return _Context.ActionHistory.Execute(action, ref errorString);
        }

        public override string DisplayValue()
        {
            return _PropInfo.CachedDisplayValue; // returns <array of 2 element(s)> string
        }

        public EditorPropertyView PropInfo
        {
            get
            {
                return _PropInfo;
            }
        }

        private UInt64 _LocalCachedCompoundGenerationId;

        public override PropertyItemBase.RefreshResult RefreshThis()
        {
            base.RefreshThis();

            // expand flag
            _CanExpand = (_PropInfo.CachedNumArrayElements != 0);

            // recreate the array items when the array changed
            if ((_LocalCachedCompoundGenerationId != _PropInfo.CachedCompoundGenerationId) || (_PropInfo.CachedNumArrayElements != Children.Count))
            {
                var wasExpanded = IsExpanded;
                var prevCount = Children.Count;

                // cache
                _LocalCachedCompoundGenerationId = _PropInfo.CachedCompoundGenerationId;

                // delete current elements
                Collapse();

                // expand to show the change
                if ( wasExpanded && _CanExpand )
                    Expand();

                return RefreshResult.TreeRefreshed;
            }

            return RefreshResult.ItemRefreshed;
        }

        public override bool ExpandElement(ref List<PropertyItemBase> newElements)
        {
            // refresh expand status
            _CanExpand = (_PropInfo.CachedNumArrayElements != 0);
  
            // create elements
            for (int i = 0; i < _PropInfo.CachedNumArrayElements; ++i)
            {
                var elementValueID = _PropInfo.CachedArrayElementGUIDs[i];
                var elementPropInfo = _PropInfo.CreateElementProp(elementValueID);
                newElements.Add(new GameData_PropertyItem(this, _Context, elementPropInfo, i, _CanEdit));
            }

            return true;
        }

        private readonly EditorContext _Context; 
        private readonly EditorPropertyView _PropInfo;
        private bool _CanEdit;
    }

}
